package chapter.tenth.item67;

import java.util.ArrayList;
import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.concurrent.CopyOnWriteArrayList;

import chapter.fourth.item16.ForwardingSet;

public class ObservableSet<E> extends ForwardingSet<E> {

	public ObservableSet(Set<E> s) {
		super(s);
	}

	/*
	 * private final List<SetObserver<E>> observers =
			new ArrayList<SetObserver<E>>();
	
	public void addObserver(SetObserver<E> observer){
		synchronized(observers){
			observers.add(observer);
		}
	}
	
	public boolean removeObserver(SetObserver<E> observer){
		synchronized(observers){
			return observers.remove(observer);
		}
	}
	
	private void notifyElementAdded(E element){
		synchronized(observers){
			for(SetObserver<E> observer:observers){
				observer.added(this, element);
			}
		}
	}*/
	
	private final List<SetObserver<E>> observers =
			new CopyOnWriteArrayList<SetObserver<E>>();

	public void addObserver(SetObserver<E> observer){
		observers.add(observer);
	}
	
	public boolean removeObserver(SetObserver<E> observer){
		return observers.remove(observer);
	}
	
	public void notifyElementAdded(E element){
		for(SetObserver<E> observer:observers)
			observer.added(this, element);
	}
	
	@Override
	public boolean add(E e) {
		boolean added = super.add(e);
		if(added)
			notifyElementAdded(e);
		return added;
	}

	@Override
	public boolean addAll(Collection<? extends E> c) {
		boolean added = false;
		for(E element: c){
			added |= add(element);
		}
		return added;
	}
	
	public static void main(String[] args) {
		ObservableSet<Integer> set = 
				new ObservableSet<Integer>(new HashSet<Integer>());
		set.addObserver(new SetObserver<Integer>(){
			public void added(ObservableSet<Integer> set, Integer element) {
				System.out.println(element);
				if(element==23)
					set.removeObserver(this);
			}
			
		});
		for(int i=0;i<100;i++){
			set.add(i);
		}
	}
	
	
	

}
